const PENDING = 'PENDING'
  FULFILLED = 'FULFILLED'
  REJECTED = 'REJECTED';

const linkedPromise = (promise, x, resolve, reject) => {
  if(x === promise) {
    return reject(new Error(' Chaining cycle detected for promise #<Promise>'))
  }
  let called;

  if(typeof (x ==='object'&& x != null) || typeof x === 'function') {
    try {
      let then = x.then;
      if(typeof then === 'function') {
        then.call(x, y => {
          if (called) return;
          called = true;
          return linkedPromise(promise, y, resolve, reject)
        }, r => {
          if (called) return;
          called = true;
          reject(r)
        })
      
      }else {
        resolve(x);
      }
    } catch (e) {
      if (called) return;
      called = true;
      reject(e)
    }
    
  }else {
    resolve(x)
  }
}

class Promise1 {
  constructor(executor) {
    this.state = PENDING;
    this.value = undefined;
    this.reason = undefined;

    this.onResolveCallback = [];
    this.onRejectedCallback = [];

    let resolve = (value) => {
      if(this.state === PENDING) {
        this.value = value;
        this.state = FULFILLED;
        this.onResolveCallback.forEach(fn => fn())
      }
    }

    let reject = (reason) => {
      if(this.state === PENDING) {
        this.reason = reason;
        this.state = REJECTED;
        this.onRejectedCallback.forEach(fn => fn())
      }
    }

    try {
      executor(resolve, reject)
    } catch (e) {
      reject(e)
    } 

  }

  then = (onFulfilled, onRejected) =>{
     //解决 onFufilled，onRejected 没有传值的问题
    //Promise/A+ 2.2.1 / Promise/A+ 2.2.5 / Promise/A+ 2.2.7.3 / Promise/A+ 2.2.7.4
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v;
    //因为错误的值要让后面访问到，所以这里也要跑出个错误，不然会在之后 then 的 resolve 中捕获
    onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err };
    // 每次调用 then 都返回一个新的 promise  Promise/A+ 2.2.7
    let promise2 = new Promise((resolve, reject) => {
      if (this.status === FULFILLED) {
        //Promise/A+ 2.2.2
        //Promise/A+ 2.2.4 --- setTimeout
        setTimeout(() => {
          try {
            //Promise/A+ 2.2.7.1
            let x = onFulfilled(this.value);
            // x可能是一个proimise
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            //Promise/A+ 2.2.7.2
            reject(e)
          }
        }, 0);
      }

      if (this.status === REJECTED) {
        //Promise/A+ 2.2.3
        setTimeout(() => {
          try {
            let x = onRejected(this.reason);
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e)
          }
        }, 0);
      }

      if (this.status === PENDING) {
        this.onResolvedCallbacks.push(() => {
          setTimeout(() => {
            try {
              let x = onFulfilled(this.value);
              resolvePromise(promise2, x, resolve, reject);
            } catch (e) {
              reject(e)
            }
          }, 0);
        });

        this.onRejectedCallbacks.push(()=> {
          setTimeout(() => {
            try {
              let x = onRejected(this.reason);
              resolvePromise(promise2, x, resolve, reject)
            } catch (e) {
              reject(e)
            }
          }, 0);
        });
      }
    });
  
    return promise2;
  }

}

const promise2 = new Promise1((resolve, reject) =>{
  console.log(`origin promise`)
  setTimeout(() => {
    resolve('成功');
  },1000);
})

promise2.then(result => console.log(result))
// promise2.catch(result => console.log(result))

Promise.defer = Promise.deferred = function () {
  let dfd = {};
  dfd.promise = new Promise((resolve,reject)=>{
      dfd.resolve = resolve;
      dfd.reject = reject;
  })
  return dfd;
}

